import * as Cesium from "cesium";
import type { FixedLengthArray } from "@utils";
import CartesianLatLng from "./utils/cartesianLatLng";

export interface DrawPolygonType {
  positions: FixedLengthArray<number, 2>[];
  outlineColor: FixedLengthArray<number, 4>;
  color: FixedLengthArray<number, 4>;
  data?: any;
  name: string;
  zIndex?: number;
}
// 绘制多边形
class DrawPolygon {
  #viewer: Cesium.Viewer;
  #positions: FixedLengthArray<number, 2>[];
  #outlineColor: FixedLengthArray<number, 4>;
  #color: FixedLengthArray<number, 4>;
  #zIndex: number;
  #name: string;
  data: any; // 自定义数据
  entity: (Cesium.Entity & { data?: any; _node?: any }) | null;
  constructor(viewer: Cesium.Viewer, options: DrawPolygonType) {
    this.#viewer = viewer;
    this.#positions = options.positions;
    this.#outlineColor = options.outlineColor
      ? options.outlineColor
      : [1, 1, 1, 1];
    this.#color = options.color ? options.color : [1, 0, 0, 1];
    this.data = options.data;
    this.#zIndex = options.zIndex ? options.zIndex : 1;
    this.entity = null;
    this.#name = options.name;
    this.#init();
  }
  #init() {
    this.entity = this.#viewer.entities.add({
      name: this.#name,
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromDegreesArray([...this.#positions.flat()])
        ),
        material: Cesium.Color.fromBytes(
          this.#color[0] * 255,
          this.#color[1] * 255,
          this.#color[2] * 255,
          this.#color[3] * 255
        ),
        height: 0, // 离地高度
        outline: true, //是否显示外线
        outlineColor: Cesium.Color.fromBytes(
          this.#outlineColor[0] * 255,
          this.#outlineColor[1] * 255,
          this.#outlineColor[2] * 255,
          this.#outlineColor[3] * 255
        ),
        zIndex: this.#zIndex,
      },
    });
    this.entity.data = this.data;
    this.entity._node = this;
  }
  click(e: any, _data?: any) {}
  setShow(show: boolean) {
    this.entity!.show = show;
  }
  update(options: any) {
    if (options.positions) {
      (this.entity as any).polygon.hierarchy = new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray([...this.#positions.flat()])
      );
    }
    if (options.color) {
      (this.entity as any).polygon.material = Cesium.Color.fromBytes(
        options.color[0] * 255,
        options.color[1] * 255,
        options.color[2] * 255,
        options.color[3] * 255
      );
    }
    if (options.outlineColor) {
      (this.entity as any).polygon.outlineColor = Cesium.Color.fromBytes(
        options.outlineColor[0] * 255,
        options.outlineColor[1] * 255,
        options.outlineColor[2] * 255,
        options.outlineColor[3] * 255
      );
    }
    if (options.zIndex) {
      (this.entity as any).polygon.zIndex = options.zIndex;
    }
    if (options.data) {
      this.entity!.data = options.data;
    }
  }
  destroy() {
    if (this.entity) {
      this.#viewer.entities.remove(this.entity);
      this.entity = null;
    }
  }
}
export interface DrawPolygonChartletType {
  positions: FixedLengthArray<number, 2>[];
  image: string;
  name: string;
  zIndex?: number;
  data?: any;
}
// 多边形贴图
class DrawPolygonChartlet {
  #viewer: Cesium.Viewer;
  #positions: FixedLengthArray<number, 2>[];
  #image: string;
  #name: string;
  #zIndex: number;
  data: any;
  entity: (Cesium.Entity & { data?: any; _node?: any }) | null;
  constructor(viewer: Cesium.Viewer, options: DrawPolygonChartletType) {
    this.#viewer = viewer;
    this.data = options.data;
    this.#image = options.image;
    this.#positions = options.positions;
    this.#name = options.name;
    this.#zIndex = options.zIndex || 1;
    this.entity = null;
    this.#init();
  }

  #init() {
    this.entity = this.#viewer.entities.add({
      name: this.#name,
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromDegreesArray([...this.#positions.flat()])
        ),
        material: new Cesium.ImageMaterialProperty({
          image: this.#image, // 替换为你的图片路径
          transparent: true, // 如果图片背景是透明的，设置为true
        }),
        zIndex: this.#zIndex,
      },
    });
    this.entity.data = this.data;
    this.entity._node = this;
  }
  click(_e: any, _data?: any) {}
  setShow(show: boolean) {
    this.entity!.show = show;
  }
  update(options: any) {
    if (options.positions) {
      (this.entity as any)!.polygon.hierarchy = new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray([...options.positions.flat()])
      );
    }
    if (options.image) {
      (this.entity as any)!.polygon.material = new Cesium.ImageMaterialProperty(
        {
          image: options.image, // 替换为你的图片路径
          transparent: true, // 如果图片背景是透明的，设置为true
        }
      );
    }
    if (options.zIndex) {
      (this.entity as any)!.polygon.zIndex = options.zIndex;
    }
    if (options.data) {
      this.entity!.data = options.data;
    }
  }
  destroy() {
    if (this.entity) {
      this.#viewer.entities.remove(this.entity);
      this.entity = null;
    }
  }
}

export interface EditPolygonType {
  points: FixedLengthArray<number, 2>[];
  color: FixedLengthArray<number, 4>;
  fillColor: FixedLengthArray<number, 4>;
}
export interface CesiumEntity extends Cesium.Entity {
  editType?: string;
  activeIndex?: number;
  data?: any;
}
// 编辑多边形
class EditPolygon {
  #viewer: Cesium.Viewer;
  #points: CesiumEntity[] = [];
  #pointsPositions: FixedLengthArray<number, 2>[] = [];
  #polygonPositions: any[] = [];
  #lines: CesiumEntity[] = [];
  #editState: boolean = false;
  #polygonPositions_back: any[] = [];
  #lineColor: Cesium.Color;
  #fillColor: Cesium.Color;
  #handler: Cesium.ScreenSpaceEventHandler | null = null;
  constructor(viewer: Cesium.Viewer, options: EditPolygonType) {
    this.#viewer = viewer;
    this.#pointsPositions = options.points;
    this.#lineColor = Cesium.Color.fromBytes(
      options.color[0] * 255,
      options.color[1] * 255,
      options.color[2] * 255,
      options.color[3] * 255
    );
    this.#fillColor = Cesium.Color.fromBytes(
      options.fillColor[0] * 255,
      options.fillColor[1] * 255,
      options.fillColor[2] * 255,
      options.fillColor[3] * 255
    );
    this.#getPoints();
  }
  // 获取多边形点坐标
  #getPoints() {
    if (this.#editState) {
      return;
    }
    this.#editState = true;
    this.#setLine();
    this.#setPoint();
  }
  // 绘制操作点
  #setPoint() {
    this.#pointsPositions.forEach(
      (item: FixedLengthArray<number, 2>, index: number) => {
        let point: CesiumEntity = this.#viewer.entities.add({
          position: Cesium.Cartesian3.fromDegrees(...item, 10),
          point: {
            pixelSize: 10,
            // 填充色
            color: this.#fillColor,
            // 是否有边框
            // outline: true,
            // 边框颜色
            outlineColor: this.#lineColor,
            // 边框宽度
            outlineWidth: 3,
          },
        });
        point.editType = "editPoint";
        point.activeIndex = index;
        this.#points.push(point);
      }
    );
  }
  // 绘制操作点
  #setLine() {
    let lines: CesiumEntity[] = [];
    for (let i = 0; i < this.#pointsPositions.length; i++) {
      let startPoint = this.#pointsPositions[i];
      let endPoint = this.#pointsPositions[i + 1]
        ? this.#pointsPositions[i + 1]
        : this.#pointsPositions[0];
      let polyline: CesiumEntity = this.#viewer.entities.add({
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArray([
            ...startPoint,
            ...endPoint,
          ]),
          material: this.#lineColor,
          width: 4,
        },
      });
      polyline.editType = "editLine";
      polyline.data = startPoint;
      lines.push(polyline);
    }
    this.#lines = lines;
  }
  // 开始编辑
  start() {
    this.#handler = new Cesium.ScreenSpaceEventHandler(
      this.#viewer.scene.canvas
    );
    let mouseClick = false;
    let mouseRightClick = false;
    let activeIndex: null | number = null;
    // 鼠标左键事件
    this.#handler.setInputAction(() => {
      mouseClick = true;
      setTimeout(() => {
        mouseClick = false;
      }, 200);
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
    this.#handler.setInputAction((e: any) => {
      if (!mouseClick) {
        return;
      }
      const picked = this.#viewer.scene.pick(e.position);
      console.log("ray", picked);
      if (picked) {
        // 点击操作点
        if (picked.id.editType == "editPoint") {
          if (activeIndex === null) {
            activeIndex = picked.id.activeIndex;
            console.log("activeIndex", activeIndex);
          } else {
            activeIndex = null;
          }
        }
        // 点击操作线
        if (picked.id.editType == "editLine") {
          const ray = this.#viewer.camera.getPickRay(e.position);
          const cartesian = this.#viewer.scene.globe.pick(
            ray!,
            this.#viewer.scene
          );
          let { lng, lat, height } = CartesianLatLng.CartesianToLatLng(
            cartesian!
          );
          let pointPosition = Cesium.Cartesian3.fromDegrees(lng, lat, 1);
          this.#addPoint(pointPosition, cartesian, picked.id.activeIndex);
        }
      } else {
        activeIndex = null;
      }
    }, Cesium.ScreenSpaceEventType.LEFT_UP);
    // 右键移除一个点
    this.#handler.setInputAction(function (_e: any) {
      mouseRightClick = true;
      setTimeout(() => {
        mouseRightClick = false;
      }, 200);
    }, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
    this.#handler.setInputAction((e: any) => {
      if (!mouseRightClick) {
        return;
      }
      // 通过平面坐标拾取对应模型
      let picked = this.#viewer.scene.pick(e.position);

      if (picked) {
        // 点击操作点
        if (picked.id.editType == "editPoint") {
          let index = picked.id.activeIndex;
          // 删除点
          this.#viewer.entities.remove(picked.id);
          this.#points.splice(index, 1);
          // 重新设置activeIndex
          this.#points.forEach((item, index) => {
            item.activeIndex = index;
          });

          // 上一条线链接下一个点
          let concatLine = this.#lines[index - 1]
            ? this.#lines[index - 1]
            : this.#lines[this.#lines.length - 1];
          let nextLine = this.#lines[index + 1]
            ? this.#lines[index + 1]
            : this.#lines[0];
          concatLine.positions[1] = nextLine.positions[0];
          // 删除线  重新设置activeIndex
          this.#viewer.entities.remove(this.#lines[index]);
          this.#lines.splice(index, 1);
          this.#lines.forEach((item, index) => {
            item.activeIndex = index;
          });
        }
      }
    }, Cesium.ScreenSpaceEventType.RIGHT_UP);

    // 鼠标移动事件
    this.#handler.setInputAction((e: any) => {
      if (activeIndex === null) {
        return;
      }
      const ray = this.#viewer.camera.getPickRay(e.position);
      const cartesian = this.#viewer.scene.globe.pick(ray!, this.#viewer.scene);
      let { lng, lat, height } = CartesianLatLng.CartesianToLatLng(cartesian!);
      this.#points[activeIndex].data = cartesian;
      this.#lines[activeIndex].positions[0] = Cesium.Cartesian3.fromDegrees(
        lng,
        lat,
        1
      );
      if (activeIndex == 0) {
        this.#lines[this.#lines.length - 1].positions[1] = position;
      } else {
        this.#lines[activeIndex - 1].positions[1] = position;
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }
  // 在多边形上添加点 并将线打断 cPosition cesium地理坐标  position EX地理坐标
  #addPoint(cPosition: any, position: any, index: number) {
    console.log(cPosition, position, index);
    // 添加点
    let point: CesiumEntity = this.#viewer.entities.add({
      position: cPosition,
      point: {
        pixelSize: 10,
        // 填充色
        color: this.#fillColor,
        // 是否有边框
        // outline: true,
        // 边框颜色
        outlineColor: this.#lineColor,
        // 边框宽度
        outlineWidth: 3,
      },
    });
    point.editType = "editPoint";
    // 点重新排序
    this.#points.splice(index + 1, 0, point);
    this.#points.forEach((item, index) => {
      item.activeIndex = index;
    });

    // 添加线段
    let startLine = this.#lines[index];
    let endLine = this.#lines[index - 1]
      ? this.#lines[index - 1]
      : this.#lines[this.#lines.length - 1];
    startLine.data[0] = position;
    let polyline: CesiumEntity = this.#viewer.entities.add({
      polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([
          endLine.data[1],
          position,
        ]),
        material: this.#lineColor,
        width: 4,
      },
    });
    polyline.data = endLine.data[1];
    polyline.editType = "editLine";

    // 线段重新排序
    this.#lines.splice(index, 0, polyline);
    this.#lines.forEach((item, index) => {
      item.activeIndex = index;
    });
  }
  // 关闭编辑
  off() {
    this.getPolygon();
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_DOWN);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_UP);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }
  // 获取多边形点集坐标
  getPolygon() {
    return this.#lines;
  }
}

export interface PolygonDrawingToolType {
  color: FixedLengthArray<number, 4>;
  fillColor: FixedLengthArray<number, 4>;
}
//采集多边形
class PolygonDrawingTool {
  #viewer: Cesium.Viewer;
  #lineColor: Cesium.Color;
  #fillColor: Cesium.Color;
  #handler: Cesium.ScreenSpaceEventHandler | null = null;
  #line1: Cesium.Entity | null = null;
  #line2: Cesium.Entity | null = null;
  polygon: (Cesium.Entity & { data?: any; _node?: any }) | null = null;
  #tempLine: Cesium.Entity | null = null; // 新增：临时线段实体
  #line1Points: any[] = [];
  #line2Points: any[] = [];
  #pointList: any[] = [];
  constructor(viewer: Cesium.Viewer, options: PolygonDrawingToolType) {
    this.#viewer = viewer;
    this.#lineColor = Cesium.Color.fromBytes(
      options.color[0] * 255,
      options.color[1] * 255,
      options.color[2] * 255,
      options.color[3] * 255
    );
    this.#fillColor = Cesium.Color.fromBytes(
      options.fillColor[0] * 255,
      options.fillColor[1] * 255,
      options.fillColor[2] * 255,
      options.fillColor[3] * 255
    );
    this.#init();
  }

  // 初始化
  #init() {
    this.#handler = null;
    this.#line1 = null;
    this.#line2 = null;
    this.polygon = null;
    this.#tempLine = null; // 初始化临时线段
    this.#line1Points = [];
    this.#line2Points = [];
    this.#pointList = [];
    this.#polygonInit();
    this.#lineInit();
  }

  // 初始化多边形
  #polygonInit() {
    this.polygon = this.#viewer.entities.add({
      polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
          // 只有当有足够的点时才创建多边形
          if (this.#pointList.length >= 6) {
            // 至少需要3个点(6个值: lng, lat, lng, lat, lng, lat)
            return new Cesium.PolygonHierarchy(
              Cesium.Cartesian3.fromDegreesArray(this.#pointList)
            );
          }
          // 否则返回空数组
          return new Cesium.PolygonHierarchy([]);
        }, false), // false 表示该属性是静态的（不会随时间变化）
        material: this.#fillColor,
        outline: true,
        outlineColor: this.#lineColor,
        outlineWidth: 3,
        perPositionHeight: true,
      },
    });

    this.polygon._node = this;
    this.#tempLine = this.#viewer.entities.add({
      polyline: {
        positions: new Cesium.CallbackProperty(() => {
          if (this.#pointList.length >= 2 && this.#pointList.length < 6) {
            return Cesium.Cartesian3.fromDegreesArray(this.#pointList);
          }
          return [];
        }, false),
        width: 3,
        material: this.#lineColor,
        clampToGround: true,
      },
    });
  }

  // 初始化线段
  #lineInit() {
    // 创建第一条线（已确认的线段）
    this.#line1 = this.#viewer.entities.add({
      polyline: {
        positions: [],
        width: 3,
        material: new Cesium.PolylineDashMaterialProperty({
          color: this.#lineColor,
          dashLength: 16,
        }),
        clampToGround: true,
      },
    });

    // 创建第二条线（动态跟随鼠标的虚线）
    this.#line2 = this.#viewer.entities.add({
      polyline: {
        positions: [],
        width: 3,
        material: new Cesium.PolylineDashMaterialProperty({
          color: this.#lineColor,
          dashLength: 16,
        }),
        clampToGround: true,
      },
    });
  }

  // 开始绘制
  start() {
    this.#handler = new Cesium.ScreenSpaceEventHandler(
      this.#viewer.scene.canvas
    );
    let mouseClick = false;
    let doubleClick = true;
    let mouseRightClick = false;

    // 单击增加点位
    this.#handler!.setInputAction(() => {
      mouseClick = true;
      setTimeout(() => {
        mouseClick = false;
      }, 200);
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    this.#handler!.setInputAction((e: any) => {
      if (!mouseClick || !doubleClick) {
        return;
      }
      const ray = this.#viewer.camera.getPickRay(e.position);
      const cartesian = this.#viewer.scene.globe.pick(ray!, this.#viewer.scene);
      let { lng, lat, height } = CartesianLatLng.CartesianToLatLng(cartesian!);
      this.#pointList = this.#pointList.concat([lng, lat]);

      // 更新线段
      if (this.#pointList.length > 2) {
        // 设置动态线起点为最新添加的点
        this.#line2Points[0] = Cesium.Cartesian3.fromDegrees(lng, lat, height);
        (this.#line2 as any).polyline!.positions = this.#line2Points;
      } else {
        // 第一个点
        this.#line1Points[0] = Cesium.Cartesian3.fromDegrees(lng, lat, height);
      }

      // 双击防抖
      doubleClick = false;
      setTimeout(() => {
        doubleClick = true;
      }, 200);
    }, Cesium.ScreenSpaceEventType.LEFT_UP);

    // 双击结束
    this.#handler!.setInputAction(() => {
      this.#off();
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

    // 右键移除一个点
    this.#handler!.setInputAction(() => {
      mouseRightClick = true;
      setTimeout(() => {
        mouseRightClick = false;
      }, 200);
    }, Cesium.ScreenSpaceEventType.RIGHT_DOWN);

    this.#handler!.setInputAction(() => {
      if (!mouseRightClick) {
        return;
      }

      if (this.#pointList.length >= 2) {
        // 移除最后两个值（一个点）
        this.#pointList.splice(-2, 2);

        // 更新动态线起点
        if (this.#pointList.length >= 2) {
          const lastLng = this.#pointList[this.#pointList.length - 2];
          const lastLat = this.#pointList[this.#pointList.length - 1];
          this.#line2Points[0] = Cesium.Cartesian3.fromDegrees(
            lastLng,
            lastLat,
            0
          );
          (this.#line2 as any)!.polyline!.positions = this.#line2Points;
        } else {
          // 如果没有足够的点，清空动态线
          this.#line2Points = [];
          (this.#line2 as any)!.polyline!.positions = [];
        }
      }
    }, Cesium.ScreenSpaceEventType.RIGHT_UP);

    // 鼠标移动带动虚线
    this.#handler!.setInputAction((e: any) => {
      const ray = this.#viewer.camera.getPickRay(e.endPosition);
      const cartesian = this.#viewer.scene.globe.pick(ray!, this.#viewer.scene);
      if (!cartesian) return;
      let { lng, lat, height } = CartesianLatLng.CartesianToLatLng(cartesian);
      // 更新动态线的终点（鼠标位置）
      if (this.#line2Points.length > 0 && this.#line2) {
        this.#line2Points[1] = Cesium.Cartesian3.fromDegrees(lng, lat, height);
        (this.#line2 as any).polyline!.positions = this.#line2Points;
      }

      // 当有两个点时，更新第一条线的预览
      if (this.#line1Points.length > 0 && this.#line1) {
        this.#line1Points[1] = Cesium.Cartesian3.fromDegrees(lng, lat, height);
        (this.#line1 as any).polyline!.positions = this.#line1Points;
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }

  //停止绘制 解除监听
  #off() {
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
    this.#handler!.removeInputAction(
      Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    );
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_DOWN);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_UP);
    this.#handler!.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    if (this.#line1) {
      this.#viewer.entities.remove(this.#line1);
      this.#line1 = null;
    }
    if (this.#line2) {
      this.#viewer.entities.remove(this.#line2);
      this.#line2 = null;
    }
    if (this.#tempLine) {
      this.#viewer.entities.remove(this.#tempLine);
      this.#tempLine = null;
    }
  }

  // 获取多边形
  getPolygon() {
    return this.#pointList;
  }

  // 添加点击监听
  click(_e: any, _data?: any) {}
  setShow(show: boolean) {
    this.polygon!.show = show;
  }

  // 销毁监听器与实例
  destroy() {
    this.#off();
    this.#line1Points = [];
    this.#line2Points = [];
    this.#pointList = [];
    if (this.#handler) {
      this.#handler!.destroy();
      this.#handler = null;
    }
    if (this.polygon) {
      this.#viewer.entities.remove(this.polygon);
      this.polygon = null;
    }
  }
}

export {
  DrawPolygon,
  DrawPolygonChartlet,
  EditPolygon, // TODO: 未完成
  PolygonDrawingTool, // TODO: 可以使用，但是需要优化
};
